﻿/*
 *  Copyright 2012 HEINER DIRECT GmbH & Co. KG
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 * @Author Rafael Dabrowski
 * 
*/
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace HDI.SharePoint.Webparts.HDITable.HDITable
{
    public partial class HDITableUserControl : UserControl
    {

        public String Title = "";
        public List<Group> Groups = new List<Group>();
        public List<string> CellFields = new List<string>();
        public Dictionary<string, string[]> GroupValues = new Dictionary<string, string[]>();

        protected void Page_Load(object sender, EventArgs e)
        {
           
            try
            {
                Controls.Add(new LiteralControl(renderTable()));
            }
            catch 
            {
               // Controls.Add(new LiteralControl(ex.Message));
            }


        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            Page.Header.Controls.Add(new LiteralControl(String.Format("<link  href='{0}' rel='stylesheet' type='text/css' />", "/_layouts/HDI.SharePoint.Webparts.HDITable/css/style.css")));
            ScriptManager.RegisterClientScriptInclude(this, this.GetType(), "HDITableJS", "/_layouts/HDI.SharePoint.Webparts.HDITable/js/HDITable.js?date=29.06.12");
        }

        public void addGroupValue(string field, string operation, string format)
        {
            GroupValues.Add(field, new string[] { operation, format });

        }

        public void addGroupValue(string field, string operation)
        {
            addGroupValue(field, operation, "{0}");
        }

        protected String renderTable()
        {

            StringBuilder sb = new StringBuilder();


            if (Groups.Count > 1 || Groups[0].Title != " " || GroupValues.Count >= 1)
            {
                sb.Append(renderHead(true));
                foreach (Group group in Groups)
                {
                    sb.Append(renderGroup(group));
                }
            }
            else
            {
                sb.Append(renderHead(false));
                foreach (Row row in Groups[0].Rows)
                {
                    sb.Append(renderRow(row, false));
                }
            }
            return String.Format("<table ID='{0}_HDITable' class='HDITable'>{1}</table>", ClientID, sb.ToString());
        }

        protected String renderHead(bool grouped)
        {
            StringBuilder sb = new StringBuilder();
            if (grouped)
            {
                sb.Append("<th>Gruppierung</th>");
            }
            foreach (String cellTitle in CellFields)
            {
                sb.Append(String.Format("<th>{0}</th>", cellTitle));
            }
            return String.Format("<tr>{0}</tr>", sb.ToString());
        }

        protected double getDouble(string text)
        {
            string newText = Regex.Replace(text, "[^0-9,\\.]+", "", RegexOptions.Compiled); ;

            return double.Parse(newText);
        }

        protected string closed(Group group)
        {
            if (group.closed)
                return "closed";
            return "";
        }

        protected String renderGroup(Group group)
        {
            StringBuilder sb = new StringBuilder();
            StringBuilder gh = new StringBuilder();
            // gh.Append(String.Format("<tr class='groupHeader depth{1}' rel='{0}' depth='{1}'><td>{2}</td>", Guid.NewGuid().ToString(), group.Depth, group.Title));
            if (group.hasSubGroups)
            {
                gh.Append(String.Format("<tr class='groupHeader depth{1} {3}' rel='{0}' depth='{1}'><td>{2}</td>", Guid.NewGuid().ToString(), group.Depth, group.Title, closed(group)));
                foreach (Group _group in group.Groups)
                {
                    sb.Append(renderGroup(_group));
                }


                foreach (string s in CellFields)
                {
                    if (GroupValues.ContainsKey(s))
                    {
                        double GroupValue = 0;
                        switch (GroupValues[s][0])
                        {
                            case "avg":
                                foreach (Group _group in group.Groups)
                                {
                                    GroupValue += _group.GroupValues[s];
                                }
                                GroupValue /= group.Groups.Count;
                                group.GroupValues.Add(s, GroupValue);
                                gh.Append(String.Format("<td>" + GroupValues[s][1] + "</td>", GroupValue));
                                break;
                            case "sum":
                                foreach (Group _group in group.Groups)
                                {
                                    GroupValue += _group.GroupValues[s];
                                }
                                group.GroupValues.Add(s, GroupValue);
                                gh.Append(String.Format("<td>" + GroupValues[s][1] + "</td>", GroupValue));

                                break;
                            case "count":
                                foreach (Group _group in group.Groups)
                                {
                                    GroupValue += _group.GroupValues[s];
                                }
                                group.GroupValues.Add(s, GroupValue);
                                gh.Append(String.Format("<td>" + GroupValues[s][1] + "</td>", GroupValue));

                                break;
                            default:
                                gh.Append("<td>Nur sum, count und avg erlaubt</td>");
                                break;
                        }
                    }
                    else { gh.Append("<td></td>"); }
                }
                gh.Append("</tr>");

            }
            else
            {
                gh.Append(String.Format("<tr class='groupHeader depth{1} {3}' rel='{0}' depth='{1}'><td>{2}</td>", Guid.NewGuid().ToString(), group.Depth, group.Title, closed(group)));
                foreach (string s in CellFields)
                {
                    if (GroupValues.ContainsKey(s))
                    {
                        double GroupValue = 0;
                        switch (GroupValues[s][0])
                        {
                            case "sum":
                                foreach (Row row in group.Rows)
                                {
                                    GroupValue += getDouble(row[s].Content);
                                }
                                group.GroupValues.Add(s, GroupValue);
                                gh.Append(String.Format("<td>" + GroupValues[s][1] + "</td>", GroupValue));
                                break;
                            case "avg":
                                foreach (Row row in group.Rows)
                                {
                                    GroupValue += getDouble(row[s].Content);
                                }
                                GroupValue /= group.Rows.Count;
                                gh.Append(String.Format("<td>" + GroupValues[s][1] + "</td>", GroupValue));
                                group.GroupValues.Add(s, GroupValue);
                                break;
                            case "count":
                                foreach (Row row in group.Rows)
                                {
                                    if (!String.IsNullOrEmpty(row[s].Content))
                                        GroupValue++;
                                }
                                group.GroupValues.Add(s, GroupValue);
                                gh.Append(String.Format("<td>" + GroupValues[s][1] + "</td>", GroupValue));
                                break;
                            default:
                                gh.Append("<td></td>");
                                break;
                        }
                    }
                    else { gh.Append("<td></td>"); }

                }
                gh.Append("</tr>");
                foreach (Row row in group.Rows)
                {
                    sb.Append(renderRow(row, true));
                }
            }

            return String.Format("{0}{1}", gh.ToString(), sb.ToString());
        }

        protected String renderRow(Row row)
        {

            return renderRow(row, false);
        }

        protected String renderRow(Row row, bool grouped)
        {
            string groupCell = "";
            if (grouped)
            {
                groupCell = "<td></td>";
            }
            StringBuilder sb = new StringBuilder(groupCell);
            foreach (string s in CellFields)
            {
                sb.Append(String.Format("<td>{0}</td>", row[s].Content));
            }

            return String.Format("<tr class='row' parent='{1}' itemid='{2}'>{0}</tr>", sb.ToString(), row.Group.SafeName, row.ItemId);
        }

        public Group addGroup(string title)
        {
            Group group = new Group(title);
            Groups.Add(group);
            return group;

        }

        public Group getGroup(string title)
        {
            return Groups.Find(x => x.Title.Equals(title));
        }

    }


    public class Group
    {
        public string Title = "";
        protected string _FName = "";
        public int Depth = 0;
        public bool closed = false;
        public Dictionary<string, double> GroupValues = new Dictionary<string, double>();



        public String SafeName
        {
            get
            {
                if (_FName == "")
                    _FName = Regex.Replace(this.Title, "[^a-zA-Z0-9_]+", "", RegexOptions.Compiled);
                return _FName;
            }
        }
        protected List<Row> _rows = new List<Row>();
        protected List<Group> _groups = new List<Group>();

        public List<Row> Rows { get { return _rows; } }
        public List<Group> Groups { get { return _groups; } }

        public bool hasSubGroups
        {
            get
            {
                if (_groups.Count >= 1)
                    return true;
                return false;
            }
        }

        public Group(string title)
        {
            Title = title;
        }

        public Group addGroup(string title)
        {
            Group group = new Group(title);
            group.Depth = this.Depth + 1;
            _groups.Add(group);
            return group;
        }
        public Group getGroup(int position)
        {
            return _groups[position];
        }
        public Group getGroup(string title)
        {
            return _groups.Find(x => x.Title.Equals(title));
        }

        public Row addRow(int id)
        {
            Row row = new Row(this, id);
            _rows.Add(row);
            return row;
        }
        public Row getRow(int position)
        {
            return _rows[position];
        }


    }
    public class Row : List<Cell>
    {
        protected Group _group;
        public Group Group { get { return _group; } }
        public int ItemId
        {
            get;
            protected set;
        }
        public Cell this[string name]
        {
            get
            {
                try
                {
                    return this.Find(x => x.Field.Equals(name));
                }
                catch
                {
                    return new Cell() { Content = "" };
                }
            }
        }
        public Row(Group pGroup, int id)
        {
            _group = pGroup;
            ItemId = id;
        }


        public Cell addCell(string field, string content)
        {
            Cell cell = new Cell(field, content);
            this.Add(cell);
            return cell;
        }
    }
    public class Cell
    {
        public String Content;
        public String Field;


        public Cell()
        {
        }

        public Cell(String field, String content)
        {
            Content = content;
            Field = field;

        }
    }
}
